﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AutomationTools.Procedimentos.Condicao
{
    /// <summary>
    /// Avalia a expressão recebida, e executa os procedimentos adequados.
    /// Recebe:     Apenas repassa o contexto.
    /// Retorna:    O retorno de vários procedimentos é feito em um object[] e o retorno de apenas um procedimento
    ///             acontece em um object.
    /// </summary>
    public class Se : IProcedimento
    {
        Func<IContexto, bool> expressao;
        public List<IProcedimento> Verdadeiro { get; set; }
        public List<IProcedimento> Falso { get; set; }

        /// <summary>
        /// Avalia a expressão recebida, e executa os procedimentos adequados.
        /// </summary>
        /// <param name="expressao">Expressão a ser avaliada na tomada da decisão.</param>
        public Se(Func<IContexto, bool> expressao)
            : this(expressao, null, null)
        { }

        /// <summary>
        /// Avalia a expressão recebida, e executa os procedimentos adequados.
        /// </summary>
        /// <param name="expressao">Expressão a ser avaliada na tomada da decisão.</param>
        /// <param name="verdadeiro">Procedimento a ser executado no caso de sucesso na avaliação</param>
        public Se(Func<IContexto, bool> expressao, IProcedimento verdadeiro)
            :this(expressao, verdadeiro, null)
        { }
        /// <summary>
        /// Avalia a expressão recebida, e executa os procedimentos adequados.
        /// </summary>
        /// <param name="expressao">Expressão a ser avaliada na tomada da decisão.</param>
        /// <param name="verdadeiro">Procedimento a ser executado no caso de sucesso na avaliação</param>
        /// <param name="falso">Procedimento a ser executado no caso de insucesso na avaliação</param>
        public Se(Func<IContexto, bool> expressao, IProcedimento verdadeiro, IProcedimento falso)
        {
            this.expressao = expressao;
            this.Verdadeiro.Add(verdadeiro);
            this.Falso.Add(falso);
        }

        public object Executar(IContexto contexto)
        {
            List<object> ret = new List<object>();
            if (expressao(contexto))
            {
                if (Verdadeiro != null)
                {
                    foreach (var item in Verdadeiro)
                        ret.Add(item.Executar(contexto));

                    return ret.Count > 1 ? ret : ret[0];
                }
            }
            else
            {
                if (Falso != null)
                {
                    foreach (var item in Falso)
                        ret.Add(item.Executar(contexto));

                    return ret.Count > 1 ? ret : ret[0];
                }
            }
            throw new Exception("Não há procedimento a ser executado.");
        }

        public void ValidarEntrada(IContexto contexto)
        {
            throw new NotImplementedException();
        }
    }
}
